package com.gem.factory.room;

import com.gem.entity.Game;
import com.gem.entity.Log;
import com.gem.entity.Room;
import com.gem.entity.User;
import com.gem.enums.MessageColorType;
import com.gem.factory.card.CardBaseFactory;
import com.gem.factory.game.GameFactory;
import com.gem.factory.log.LogFactory;
import com.gem.factory.user.UserFactory;
import com.gem.netty.entity.CurrentUser;
import com.gem.netty.session.GroupSession;
import com.gem.netty.session.GroupSessionFactory;
import com.gem.utils.R;
import com.sun.org.apache.regexp.internal.RE;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Author: Xhy
 * CreateTime: 2022-09-21 13:47
 */
@Component
public class RoomFactory {

    // 房间id 房间
    private static ConcurrentHashMap<String, Room> rooms = new ConcurrentHashMap();

    public static R verifyJoin(String roomId,String userId){
        // 是否存在该房间
        if (!RoomFactory.existRoom(roomId)){
            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message(roomId+":房间不存在");
        }

        // 是否重复加入
        if (RoomFactory.existRoomInUser(roomId,userId)){

            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("你已存在该房间").code(201).data("data",RoomFactory.get(roomId).getState());
        }
        // 是否游戏开始
        if (RoomFactory.get(roomId).getState()){
            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("房间内游戏已开始");

        }

        // 房间人数是否已满
        if (RoomFactory.existRoomFull(roomId)){
            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("房间已满");
        }
        return R.ok().message("已加入房间");
    }

    /**
     * 加入房间
     * @param roomId
     * @param userId
     */
    public static R join(String roomId,String userId){

        R r = verifyJoin(roomId, userId);
        if (!r.getState()){
            return r;
        }
        Room room = rooms.get(roomId);
        User user = new User();
        user.setId(userId);
        user.setName(UserFactory.get(userId));
        user.setType(true);
        room.getUsers().add(user);
        room.getCurPeople().set(room.getUsers().size());

        return r;
    }


    private static String getRoomId(){
        String roomId = "";
        for (int i = 0; i < 4; i++) {
            roomId+=String.valueOf(new Random().nextInt(10));
        }
        while (RoomFactory.existRoom(roomId)){
            getRoomId();
        }
        return roomId;
    }

    /**
     * 创建房间
     * @param roomName 房间名
     * @param roomOwnerId 房主id
     * @return
     */
    public static R createRoom(String roomName,String roomOwnerId){

        if (!UserFactory.existUser(roomOwnerId)){
            return R.error().message("用户id不存在");
        }
        String roomId = getRoomId();
        Room room = new Room();
        room.setRoomOwnerId(roomOwnerId);
        room.setRoomName(roomName);
        room.setRoomId(roomId);
        room.setState(false);
        room.setUsers(new HashSet<>());
        room.setRoomOwnerName(UserFactory.get(room.getRoomOwnerId()));
        room.setUsers(new HashSet<>());
        room.setCreateTime(new Date());
        GroupSession groupSession = GroupSessionFactory.getGroupSession();
        HashSet<String> set = new HashSet<>();
        set.add(roomOwnerId);
        rooms.put(room.getRoomId(),room);
        groupSession.createGroup(roomId,set);
        // 记录操作日志
        Log log = new Log();
        log.setMessage(UserFactory.get(roomOwnerId)+"创建房间");
        log.setDate(new Date());
        log.setMessageColor(MessageColorType.SYSTEM_MESSAGE.type);
        LogFactory.add(roomId,log);
        return R.ok().message("创建成功").data("data",room);
    }

    /**
     * 获取房间内成员
     * @param roomId
     * @return
     */
    public static Set<User> getRoomInMembers(String roomId){
        return rooms.get(roomId).getUsers();
    }

    /**
     * 获取所有房间
     * @return
     */
    public static Map<String, Room> listRooms(){
        return rooms;
    }

    /**
     * 退出房间
     * @param roomId
     * @param userId
     */
    public static void quitRoom(String roomId,String userId){

            Set<User> members = getRoomInMembers(roomId);
            Iterator<User> iterator = members.iterator();
            while (iterator.hasNext()) {
                User next = iterator.next();
                if (next.equals(userId)){
                    iterator.remove();
                    break;
                }
            }
            get(roomId).getCurPeople().getAndDecrement();
            // 是否剩最后一个人，删除房间
            existRoomEmpty(roomId);
    }

    /**
     * 获取房间
     * @param roomId
     * @return
     */
    public static Room get(String roomId){
        return rooms.get(roomId);
    }

    /**
     * 房间是否已满
     * @param roomId
     * @return
     */
    public static boolean existRoomFull(String roomId){
        return rooms.get(roomId).getCurPeople().get() == 4;
    }

    /**
     * 房间是否已空
     * @param roomId
     */
    public static void existRoomEmpty(String roomId){
        if (rooms.get(roomId).getCurPeople().get() == 0){
            remove(roomId);
        }
    }


    /**
     * 删除房间
     * @param roomId
     */
    public static void remove(String roomId){
        rooms.remove(roomId);
    }

    /**
     * 是否存在房间
     * @param roomId
     * @return
     */
    public static boolean existRoom(String roomId){
        return rooms.containsKey(roomId);
    }

    /**
     * 房间内是否存在该用户
     * @param roomId
     * @param userId
     * @return
     */
    public static boolean existRoomInUser(String roomId,String userId){
        Set<User> users = rooms.get(roomId).getUsers();
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()) {
            User user = iterator.next();
            if (user.getId().equals(userId)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 是否满足要求开始游戏
     * @param roomId
     * @return
     */
    public static boolean existStartGame(String roomId){
        return rooms.get(roomId).getCurPeople().get() >=2;
    }

    /**
     * 搜索房间
     * @param roomId
     * @return
     */
    public static List<Room> search(String roomId) {
        List<Room> rooms = RoomFactory.rooms.values().stream().collect(Collectors.toList());
        return like(roomId, rooms);
    }

    /**
     * 模糊查询
     * @param roomId
     * @param list
     * @return
     */
    public static List<Room> like(String roomId, List<Room> list) {
        List results = new ArrayList();
        Pattern pattern = Pattern.compile(roomId);
        for (int i = 0; i < list.size(); i++) {
            Matcher matcher = pattern.matcher(list.get(i).getRoomId());
            if (matcher.find()) {
                results.add(list.get(i));
            }
        }
        return results;
    }

    /**
     * 清理空房
     */
    public static void clear(){
        rooms.forEach((k,v)->{
            if (v.getCurPeople().get() == 0 || v.getUsers().size() ==0 ){
                rooms.remove(k);
            }
        });

    }


    final static String[] roobotNames = {"测试机器人","开发机器人","架构师机器人","UI机器人","产品机器人","运维机器人","前端机器人","后端机器人","苦逼机器人"};
    // 返回机器人id
    public static void joinRobot(String roomId, Integer robotLevel,String robotId) {


        Room room = rooms.get(roomId);
        String robotName = robotLevel == 0 ? roobotNames[new Random().nextInt(roobotNames.length)] : "王者-";
        for (int i = 0; i < 6; i++) {
            int random = (int)(Math.random()*9);
            robotName+=random;
        }
        User user = new User();
        user.setRobotLevel(robotLevel);
        user.setId(robotId);
        user.setName(robotName);
        user.setType(false);
        room.getUsers().add(user);
        room.getCurPeople().getAndIncrement();
    }

    public static boolean removeUser(Room room, String userId) {
        String roomId = room.getRoomId();
        Iterator<User> iterator = room.getUsers().iterator();
        Boolean flag = false;
        while (iterator.hasNext()) {
            User user = iterator.next();
            String uId = user.getId();
            if (uId.equals(userId)){
                flag = true;
                // 游戏内成员删除
                iterator.remove();
                Game game = GameFactory.get(roomId);
                if (game!=null){
                    removeGameInUserByUserId(game,userId);
                }
                final AtomicInteger curPeopleSize = room.getCurPeople();
                curPeopleSize.getAndDecrement();
                // 当前房间是否为空或者都为机器人的话则将房间删除
                final long robotCount = room.getUsers().stream().filter(u -> !u.getType()).count();
                if (curPeopleSize.get() == 0 || Long.valueOf(curPeopleSize.get()) == robotCount){
                    if(game!=null){
                        GameFactory.remove(game.getRoomId());
                        CardBaseFactory.remove(roomId);
                    }
                    RoomFactory.remove(roomId);
                    LogFactory.remove(roomId);
                }
            }
        }
        // 如果是房主离开再次选择房主
        if (room.getRoomOwnerId().equals(userId)){
            if (room.getUsers().iterator().hasNext()){
                room.setRoomOwnerId(room.getUsers().iterator().next().getId());
            }
        }
        return flag;
    }
    private static void removeGameInUserByUserId(Game game,String uId){
        Iterator<CurrentUser> userIt = game.getUsers().iterator();
        while (userIt.hasNext()){
            CurrentUser user = userIt.next();
            if (user.getId().equals(uId)){
                // 把用户手里的宝石回收
                TreeMap<Integer, Integer> userOwnGems = user.getGems();
                Map<Integer, Integer> gameGems = game.getGems();
                userOwnGems.forEach((k,v)->{
                    gameGems.put(k,gameGems.get(k)+v);
                });
                userIt.remove();
            }
        }
    }
}
